﻿using Crux.Core.SQL.Formatter.Core.Util;

namespace Crux.Core.SQL.Formatter.Core;
/// <summary>
/// 
/// </summary>
public class InlineBlock
{
    private int level;
    private readonly int maxColumnLength;
    /// <summary>
    /// 
    /// </summary>
    /// <param name="maxColumnLength"></param>
    public InlineBlock(int maxColumnLength)
    {
        this.maxColumnLength = maxColumnLength;
        level = 0;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="tokens"></param>
    /// <param name="index"></param>
    public void BeginIfPossible(JSLikeList<Token>? tokens, int index)
    {
        if (level == 0 && IsInlineBlock(tokens, index))
        {
            level = 1;
        }
        else if (level > 0)
        {
            level++;
        }
        else
        {
            level = 0;
        }
    }
    /// <summary>
    /// 
    /// </summary>
    public void End()
    {
        level--;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public bool IsActive()
    {
        return level > 0;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="tokens"></param>
    /// <param name="index"></param>
    /// <returns></returns>
    private bool IsInlineBlock(JSLikeList<Token>? tokens, int index)
    {
        if (tokens is null)
        {
            return false;
        }

        var length = 0;
        var level = 0;

        for (var i = index; i < tokens.Size(); i++)
        {
            var token = tokens.Get(i);
            length += token!.value.Length;

            if (length > maxColumnLength)
            {
                return false;
            }

            if (token.type == TokenTypes.OPEN_PAREN)
            {
                level++;
            }
            else if (token.type == TokenTypes.CLOSE_PAREN)
            {
                level--;
                if (level == 0)
                {
                    return true;
                }
            }

            if (IsForbiddenToken(token))
            {
                return false;
            }
        }

        return false;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="token"></param>
    /// <returns></returns>
    private static bool IsForbiddenToken(Token token)
    {
        return token.type == TokenTypes.RESERVED_TOP_LEVEL
            || token.type == TokenTypes.RESERVED_NEWLINE
            || token.type == TokenTypes.BLOCK_COMMENT
            || token.value.Equals(";");
    }
}